#ifndef LOGIN_SERVER_IMP_H
#define LOGIN_SERVER_IMP_H

#include "login_server.h"
#include "challenge_package.h"
#include "challenge_response.h"
#include "keyexchange_package.h"
#include "keyexchange_response.h"
#include "i_auth_client.h"
#include "i_package_codec.h"
#include "i_package_handler.h"
#include "arc4_codec.h"

#include <osrng.h>
#include <sha.h>
#include <hmac.h>

#include <algorithm>
using namespace std;
using namespace CryptoPP;

namespace login_server_detail
{
	class State
	{
	public:
		typedef boost::shared_ptr<State> Ptr;
		virtual bool handle(IPackage* package, Imp* loginClient) = 0;
	};

	class KeyExchangePhase : public State
	{
	public:
		virtual bool handle(IPackage* package, Imp* loginClient);
	};

	class ChallengePhase : public State
	{
	public:
		virtual bool handle(IPackage* package, Imp* loginClient);
	};

	class Imp : public IIoAttachment, public IAuthClient, public IPackageHandler, public IAuthCallback, public boost::enable_shared_from_this<Imp>
	{
	public:
		scoped_array<unsigned char> challengeNonse_;
		scoped_array<unsigned char> challengeSignature_;
		boost::shared_ptr<State> currentState_;
		string userName_;
		string password_;
		boost::shared_ptr<IAuthRequester> authRequester_;
		scoped_array<unsigned char> scodigestOfUserPassword_;
		scoped_array<byte> outKey_;
		UPeer::Ptr peer_;
		LoginAuthDelegate failedDelegate_;
		LoginAuthDelegate successDelegate_;

		void start(UPeer::Ptr peer);

		virtual void onSetAuthInfo(const std::string& userName, const std::string& password);

		inline void setAuthRequester(boost::shared_ptr<IAuthRequester> authRequester)
		{
			authRequester_ = authRequester;
		}

		inline void setLoginAuthDelegate(LoginAuthDelegate failedDelegate, LoginAuthDelegate successDelegate)
		{
			failedDelegate_ = failedDelegate;
			successDelegate_ = successDelegate;
		}

		virtual void handle(IPackage* package, IIoHandler::Ptr ioHandler);

		void onKeyExchanged(const scoped_array<byte>& finalNonce);
	};
}

#endif